//
//  main.cpp
//  sad
//
//  Created by Christopher Kemsley on 1/27/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//






#include "ModuleFactory.hpp"
#include "PubSub.hpp"
#include "URL.hpp"

#include "DelayedBinding.hpp"

#include "URL.hpp"
#include "Exception.hpp"

#include <unistd.h>


#include "Settings.hpp"
#include "Codec.hpp"
#include "Log.hpp"
#include "SimulationParameters.hpp"
#include "StatisticsServer.hpp"


using namespace Sim ;



struct	MainSettings : public Settings
{
	URL				logPath ;
	URL				simPath ;
	URL				statsPath ;
	ModelVariant	module ;
	Interval		runDuration ;
	
	MainSettings ()
	:	Settings ("Main")
	,	logPath		( "./" )
	,	simPath		( "./" )
	,	statsPath	( "./main.xml" )
	,	module		(  )
	,	runDuration	( 10 , 0 , 0 )
		{
		add ( "logConfigURL" , logPath ) ;
		add ( "simConfigURL" , simPath ) ;
		add ( "model" , module ) ;
		add ( "runDuration" , runDuration ) ;
		add ( "statsConfigURL" , statsPath ) ;
		}
	
	virtual void		validate ()
		{
		if ( ! module.isComplete() )
			ThrowException ( "MainSettings" , "Root model's variant information isn't complete" , __FILE__,__LINE__ ) ;
		}
} ;







int main (int argc, char * argv[]) {
	try
		{
		char	buffer [200] ;
		getcwd ( buffer , 200 ) ;
		
		URL		pwdURL		( buffer , true ) ;
		
		if ( ! pwdURL.isAbsolute() )
			{
			std::cout << "Fatal error: PWD wasn't absolute!\n\n" ;
			return -1 ;
			}
		
		pwdURL.makeBaseURL() ;
		
		
		URL		mainURL		( argc>1 ? argv[1] : "./main.xml" ) ;
		
		URL		mainBase	=	mainURL . directoryURL() ;
		mainBase			=	mainBase . absoluteURL() ;
		mainBase.makeBaseURL() ;
		std::cout << "URL: " << URL("./").absoluteURL() << "\n" ;
		
		mainURL		=	URL ( mainURL.filename() ) ;
		
		
		
		MainSettings	appInfo ;
		
		if ( Codec :: decode<URL,Settings> ( mainURL , appInfo ) )
			{
			Log :: loadConfiguration	( appInfo.logPath ) ;
			SimulationParameters :: loadConfiguration ( appInfo.simPath ) ;
			Statistics::Server::loadConfiguration ( appInfo.statsPath ) ;
			
			
			Log::notice("main") << "Root module: " << appInfo.module ;
			Log::notice("main") << "Run duration: " << appInfo.runDuration ;
			
			Model	*	root	=	ModuleFactory :: create ( appInfo.module ) ;
			
			if ( root == 0 )
				{
				std::stringstream s ;
				s << "Failed to create root model. URL = " << appInfo.module ;
				
				Exception c ( "main" , s.str() , __FILE__,__LINE__ ) ;
				Log :: logException(c) ;
				exit ( -1 ) ;
				}
			
			DelayedBinding :: runAll () ;
			
			System::shared() . runForDuration ( appInfo.runDuration ) ;
			
			Log::flush() ;
			
			delete root ;
			}
		else
			{
			Log::error("main") << "Application info not found. Either (1) specify a main.xml file ('sad /path/to/main.xml') or (2) have 'main.xml' in the PWD\n\n" ;
			
			Log::flush() ;
			}
		}
	catch ( Exception & e )
		{
		Log :: logException ( e ) ;
		std::cout << "\n\n\n***** Exiting due to exception *****\n" ;
		return -1 ;
		}
	
	
	
	
	
	
	
    return 0;
}



